Skip to content

Reject unbalanced parentheses in profile expressions#36550

Merged
bclozel merged 1 commit intospring-projects:mainfrom
daguimu:fix/profiles-parser-unbalanced-parentheses-36540
Apr 7, 2026
Merged

Reject unbalanced parentheses in profile expressions#36550
bclozel merged 1 commit intospring-projects:mainfrom
daguimu:fix/profiles-parser-unbalanced-parentheses-36540

Conversation

@daguimu
Copy link
Copy Markdown
Contributor

@daguimu daguimu commented Mar 27, 2026

Problem

ProfilesParser silently accepts unbalanced parentheses in profile expressions. For example, Profiles.of("dev)") or @Profile("dev)") is accepted without error and treated as "dev". This can lead to unexpected behavior where malformed profile annotations are silently interpreted instead of being rejected.

Root Cause

In ProfilesParser.parseTokens(), when a closing ) is encountered outside of a Context.PARENTHESIS context (i.e., without a matching opening (), the parser merges the current elements, clears state, and continues parsing instead of raising a validation error. Similarly, when all tokens are consumed while still inside a PARENTHESIS context (unmatched opening (), the method returns normally without detecting the imbalance.

Fix

  • In the ")" case of parseTokens(), reject unmatched closing parentheses by calling assertWellFormed(expression, false) when not in PARENTHESIS context, instead of silently continuing
  • After the token loop, add assertWellFormed(expression, context != Context.PARENTHESIS) to reject unmatched opening parentheses when tokens are exhausted
  • Fix an existing test (ofAndExpressionWithoutSpaces) that inadvertently relied on this lenient behavior by using "spring&framework)" instead of "(spring&framework)"

Tests Added

Change Point Test
Reject unmatched ) at top level malformedExpressionsWithUnbalancedParentheses() — verifies "dev)", "spring&framework)", "(dev))" all throw IllegalArgumentException
Reject unmatched ( when tokens exhaust malformedExpressionsWithUnbalancedParentheses() — verifies "(dev", "((dev)" throw IllegalArgumentException
Fix existing test input ofAndExpressionWithoutSpaces() — now uses "(spring&framework)" and still passes assertAndExpression checks

All 37 tests in ProfilesTests pass, including all pre-existing tests (no regressions).

Impact

Expressions with unbalanced parentheses that were previously silently accepted will now throw IllegalArgumentException with a "Malformed profile expression" message. This is consistent with the existing behavior for standalone "(" and ")" which already throw. Well-formed expressions are not affected.

Fixes #36540

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Mar 27, 2026
@daguimu daguimu force-pushed the fix/profiles-parser-unbalanced-parentheses-36540 branch from 63c73f3 to d3ac9ca Compare March 27, 2026 07:16
@bclozel bclozel self-assigned this Apr 7, 2026
@bclozel bclozel added in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Apr 7, 2026
@bclozel bclozel added this to the 7.1.0-M1 milestone Apr 7, 2026
@bclozel bclozel force-pushed the fix/profiles-parser-unbalanced-parentheses-36540 branch from d3ac9ca to 9db885c Compare April 7, 2026 13:38
ProfilesParser.parseTokens() silently accepts unbalanced parentheses
in profile expressions such as "dev)" or "(dev", treating them as
valid. This can lead to unexpected behavior where malformed @Profile
annotations are silently interpreted instead of being rejected.

This commit tightens the validation in parseTokens() to reject:
- Unmatched closing parenthesis at the top level
- Unmatched opening parenthesis when tokens are exhausted

Also fixes an existing test that inadvertently relied on this lenient
behavior by using "spring&framework)" instead of "(spring&framework)".

Closes spring-projectsgh-36550

Signed-off-by: daguimu <daguimu.geek@gmail.com>
@bclozel bclozel force-pushed the fix/profiles-parser-unbalanced-parentheses-36540 branch from 9db885c to d37d7ab Compare April 7, 2026 13:39
@bclozel bclozel closed this in d37d7ab Apr 7, 2026
@bclozel bclozel merged commit d37d7ab into spring-projects:main Apr 7, 2026
1 check passed
@bclozel
Copy link
Copy Markdown
Member

bclozel commented Apr 7, 2026

Thanks for your contribution @daguimu !

@daguimu daguimu deleted the fix/profiles-parser-unbalanced-parentheses-36540 branch April 7, 2026 15:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ProfilesParser silently accepts unbalanced parentheses in profile expressions

3 participants